
#include "lua_func_lib.h"
#include "RA8876.h"
#include "RA8876_API.h"
#include "bsp.h"
#include "dwt_delay.h"
#include "fatfs.h"
#include "lcd.h"
#include "main.h"
#include "reg_ssd2828.h"
#include "ssd2828.h"
#include "tester.h"
#include "util.h"
#include "videomodes.h"
#include <string.h>

extern struct Tester test10;
extern UART_HandleTypeDef huart1;

/**
 * @brief drawFile lua export
 *
 * @param L
 */
int lua_drawFile(lua_State *L)
{
	const char *fn = lua_tostring(L, 1);

	drawFile((char *)fn);

	return 1;
}

int lua_set_lvds_color_mode(lua_State *L)
{
	uint8_t v = lua_tointeger(L, 1);
	set_lvds_color_mode(v);
	return 0;
}

/************************************************************************************************
 *
 *  								Functions Export to Lua
 *
 ***********************************************************************************************/

int lua_check_version(lua_State *L)
{
	const char *str = lua_tostring(L, 1);
	uint32_t HardWare;
	uint32_t SoftWare;
	uint32_t Fix;
	char version[32] = {};

	sscanf(str, "%lu.%lu.%lu", &HardWare, &SoftWare, &Fix);
	sprintf(version, "%lu.%lu.%lu", test10.version.major,
		test10.version.miner, test10.version.fix);

	int cpv = compareVersion(str, version);
	if (cpv < 0) {
		printf("[Version] lua %lu.%lu.%lu\r\n", test10.version.major,
		       test10.version.miner, test10.version.fix);
		printf("[Version] fw %lu.%lu.%lu\r\n", test10.version.major,
		       test10.version.miner, test10.version.fix);
	}

	return cpv;
}

/**
 * @brief: 打开模块背光
 * @note:
 * @param
 * @retval:
 */
static int lua_led_on(lua_State *L)
{
	// PCout(13) = 1;
	HAL_GPIO_WritePin(ULED2_GPIO_Port, ULED2_Pin, GPIO_PIN_RESET);
	return 1;
}

/**
 * @brief: 关闭模块背光
 * @note:
 * @param {type}
 * @retval:
 */
static int lua_led_off(lua_State *L)
{
	// PCout(13) = 0;
	HAL_GPIO_WritePin(ULED2_GPIO_Port, ULED2_Pin, GPIO_PIN_SET);
	return 1;
}

/**
 * @brief: ms延迟函数
 * @note:
 * @param (1-long-毫秒数)
 * @retval:
 */
static int lua_delay(lua_State *L)
{
	int num;
	num = lua_tointeger(L, 1);
	HAL_Delay(num);
	return 1;
}

/**
 * @brief lua调用此函数, 传递一个字符串给C, C打印这个字符串
 *
 * @param L
 * @return int
 */
static int lua_printString(lua_State *L)
{
	const char *str = lua_tostring(L, 1);
	printf(str);
	return 1;
}

/**
 * @brief lua传递一个float给C, C打印这个float
 *
 * @param L
 * 		1 - float - 一个浮点数
 * @return int
 */
static int lua_printFloat(lua_State *L)
{
	float num = lua_tonumber(L, 1);
	printf("get float number for lua %f\r\n", num);
	return 1;
}

/**
 * @brief 从C向lua传递多个字符串
 *
 * @param L
 * @return int
 */
static int lua_testPushString(lua_State *L)
{
	const char *str1 = "string from C 1\r\n";
	lua_pushstring(L, str1);

	const char *str2 = "string from C 2\r\n";
	lua_pushstring(L, str2);

	const char *str3 = "string from C 3\r\n";
	lua_pushstring(L, str3);
	return 3;
}

static int lua_testPushInts(lua_State *L)
{
	uint8_t data[4] = { 0xaa, 0xbb, 0xcc, 0xdd };
	for (uint8_t i = 0; i < 4; i++) {
		lua_pushinteger(L, data[i]);
	}
	return 4;
}

/**
 * @brief 45pin接口下, 控制IO口输出电平
 *
 * @param L
 * 			1 - uint8_t - IO State(1: High, 0:Low)
 * @return int
 */
static int lua_io2(lua_State *L)
{
	int num = lua_tointeger(L, 1);
	HAL_GPIO_WritePin(UIO_2_GPIO_Port, UIO_2_Pin,
			  num ? GPIO_PIN_SET : GPIO_PIN_RESET);
	return 1;
}

/**
 * @brief 45pin接口下, 控制IO口输出电平
 *
 * @param L
 * 			1 - uint8_t - IO State(1: High, 0:Low)
 * @return int
 */
static int lua_io3(lua_State *L)
{
	int num = lua_tointeger(L, 1);
	HAL_GPIO_WritePin(UIO_3_GPIO_Port, UIO_3_Pin,
			  num ? GPIO_PIN_SET : GPIO_PIN_RESET);
	return 1;
}

/**
 * @brief 45pin接口下, 控制IO口输出电平
 *
 * @param L
 * 			1 - uint8_t - IO State(1: High, 0:Low)
 * @return int
 */
static int lua_io4(lua_State *L)
{
	int num = lua_tointeger(L, 1);
	HAL_GPIO_WritePin(UIO_4_GPIO_Port, UIO_4_Pin,
			  num ? GPIO_PIN_SET : GPIO_PIN_RESET);
	return 1;
}

/**
 * @brief 45pin接口下, 控制IO口输出电平
 *
 * @param L
 * 			1 - uint8_t - IO State(1: High, 0:Low)
 * @return int
 */
static int lua_io5(lua_State *L)
{
	int num = lua_tointeger(L, 1);
	HAL_GPIO_WritePin(UIO_5_GPIO_Port, UIO_5_Pin,
			  num ? GPIO_PIN_SET : GPIO_PIN_RESET);
	return 1;
}

/**
 * @brief lua io write
 *
 * @param L
 * 	ioNum io number at adu-45
 * 	state io state to write
 * @return int
 */
static int lua_ioWrite(lua_State *L)
{
	int ioNum = lua_tointeger(L, 1);
	int state = lua_tointeger(L, 2);

	GPIO_TypeDef *port = BSP_getSTM32PortNmb(ioNum);
	uint16_t pin = BSP_getSTM32PinNmb(ioNum);

	HAL_GPIO_WritePin(port, pin, state ? GPIO_PIN_SET : GPIO_PIN_RESET);

	return 0;
}

/**
 * @brief read adu-45 pin
 *
 * @param L
 * 	ioNum adu-45 pin number
 * 	return pin state
 * @return int
 */
static int lua_ioRead(lua_State *L)
{
	int ioNum = lua_tointeger(L, 1);
	GPIO_PinState state;

	// GPIO_TypeDef *port = NULL;
	// uint16_t pin = getGpio(ioNum, port);
	GPIO_TypeDef *port = BSP_getSTM32PortNmb(ioNum);
	uint16_t pin = BSP_getSTM32PinNmb(ioNum);

	state = HAL_GPIO_ReadPin(port, pin);

	if (state == GPIO_PIN_RESET) {
		lua_pushinteger(L, 0);
	} else {
		lua_pushinteger(L, 1);
	}

	return 1;
}

//{"readKey", lua_readKey},
/**
 * @brief get key 0, 1 when lua is running
 *
 * @param L 1#, key number [0..1]
 * @return int 0:low, 1:high, -1:error
 */
static int lua_readKey(lua_State *L)
{
	int keyNum = lua_tointeger(L, 1);

	lua_pushinteger(L, BSP_getKeyState(keyNum));

	return 1;
}

/**
 * @brief initial io with io number
 *
 * @note in lua:
 * 	param ioNum: io number [2,3,4,5,14,15,16]
 * 	param mode: io mode [OUTPUT_PP, OUTPUT_OD, INPUT]
 * 	param pull: io pull type [NOPULL, PULLUP, PULLDOWN]
 * @param L
 * @return int
 */
static int lua_ioInitial(lua_State *L)
{
	int ioNum = lua_tointeger(L, 1);
	const char *mode = lua_tostring(L, 2);
	const char *pull = lua_tostring(L, 3);
	if (test10.debug) {
		printf("[GPIO] get setting %d, %s, %s\r\n", ioNum, mode, pull);
	}

	GPIO_TypeDef *port = BSP_getSTM32PortNmb(ioNum);
	uint16_t pin = BSP_getSTM32PinNmb(ioNum);

	if (test10.debug) {
		printf("[GPIO] pin %d port %d\r\n", pin, (int)&port);
	}

	GPIO_InitTypeDef GPIO_InitStruct = { 0 };

	GPIO_InitStruct.Pin = pin;

	if (strcmp(mode, "OUTPUT_PP") == 0) {
		GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
	} else if (strcmp(mode, "OUTPUT_OD") == 0) {
		GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;
	} else if (strcmp(mode, "INPUT") == 0) {
		GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
	} else {
		printf("[GPIO] mode setting error\r\n");
		Error_Handler();
	}

	if (strcmp(pull, "NOPULL") == 0) {
		GPIO_InitStruct.Pull = GPIO_NOPULL;
	} else if (strcmp(pull, "PULLUP") == 0) {
		GPIO_InitStruct.Pull = GPIO_PULLUP;
	} else if (strcmp(pull, "PULLDOWN") == 0) {
		GPIO_InitStruct.Pull = GPIO_PULLDOWN;
	} else {
		printf("[GPIO] pull setting error\r\n");
		Error_Handler();
	}

	GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;

	HAL_GPIO_Init(port, &GPIO_InitStruct);

	return 0;
}

/**
 * @brief adu-45 pin deinitial
 *
 * @param L
 * @return int
 */
static int lua_ioDeInitial(lua_State *L)
{
	// TODO
	return 0;
}

/**
 * @brief set test image change interval
 *
 * @param L
 * 			1 - uint32_t - micro second
 * @return int
 */
static int lua_t10_setInterval(lua_State *L)
{
	int num = lua_tointeger(L, 1);

	if (num >= 0) {
		test10.img_interval_ms = num;
	} else {
		printf("ERROR: Image Change Interval < 0\r\n");
		return 0;
	}

	return 1;
}

/**
 * @brief delay micro second
 *
 * @param L
 * 			1 - uint32_t - micro second number
 * @return int
 */
static int lua_t10_delayMs(lua_State *L)
{
	int num = lua_tointeger(L, 1);

	if (num >= 0) {
		HAL_Delay(num);
	} else {
		printf("ERROR: lua_t10_delayMs < 0\r\n");
		return 0;
	}

	return 1;
}

/**
 * @brief set work mode MIPI-DBI typeA
 *
 * @param L
 * @return int
 */
static int lua_t10_DBI_A(lua_State *L)
{
	// TODO
	return 1;
}

/**
 * @brief set work mode MIPI-DBI typeB
 *
 * @param L
 * @return int
 */
static int lua_t10_DBI_B(lua_State *L)
{
	// TODO
	return 1;
}

/**
 * @brief set work mode MIPI-DBI typeC
 *
 * @param L
 * @return int
 */
static int lua_t10_DBI_C(lua_State *L)
{
	// TODO
	return 1;
}

/**
 * @brief set work mode MIPI-DPI (RGB)
 *
 * @param L
 * 			(1-long-h_size)
 * 			(2-uint8_t-h_pause_width)
 * 			(3-uint8_t-h_back_porch)
 * 			(4-uint8_t-h_front_porch)
 * 			(5-uint16_t-v_size)
 * 			(6-uint8_t-v_pause_width)
 * 			(7-uint8_t-v_back_porch)
 * 			(8-uint8_t-v_front_porch)
 * 			(9-uint8_t-h_sync_polority)
 * 			(10-uint8_t-v_sync_polority)
 * 			(11-uint8_t-de_polority)
 * 			(12-uint8_t-clock_edge)
 * 			(13-uint8_t-FPS_frame_per_second)
 * @return int
 */
static int lua_t10_DPI(lua_State *L)
{
	test10.mipi_type = MIPI_DPI;

	test10.timing.ha = lua_tointeger(L, 1);
	test10.timing.hsw = lua_tointeger(L, 2);
	test10.timing.hbp = lua_tointeger(L, 3);
	test10.timing.hfp = lua_tointeger(L, 4);
	test10.timing.va = lua_tointeger(L, 5);
	test10.timing.vsw = lua_tointeger(L, 6);
	test10.timing.vbp = lua_tointeger(L, 7);
	test10.timing.vfp = lua_tointeger(L, 8);
	test10.timing.hsp = lua_tointeger(L, 9);
	test10.timing.vsp = lua_tointeger(L, 10);
	test10.timing.dep = lua_tointeger(L, 11);
	test10.timing.clkEdge = lua_tointeger(L, 12);
	test10.fps = lua_tointeger(L, 13);

	print_dpi_timing(&test10.timing);
	printf("[DPI] FPS Setting = %d\r\n", test10.fps);

	if (RA8876_check_connection()) {
		printf("ERROR RA8876 not exist\r\n");
		Error_Handler();
	} else {
		printf("[RA8876] Probe Success\r\n");
	}

	RA8876_initial(&test10.timing, test10.fps);

	return 1;
}

/**
 * @brief set work mode MIPI-DPI (RGB)
 *
 * @param L
 * 			1 - uint16_t - h_size)
 * 			2 - uint8_t - h_pause_width)
 * 			3 - uint8_t - h_back_porch)
 * 			4 - uint8_t - h_front_porch)
 * 			5 - uint16_t - v_size)
 * 			6 - uint8_t - v_pause_width)
 * 			7 - uint8_t - v_back_porch)
 * 			8 - uint8_t - v_front_porch)
 * 			9 - uint8_t - h_sync_polority)
 * 			10 - uint8_t - v_sync_polority)
 * 			11 - uint8_t - de_polority)
 * 			12 - uint8_t - clock_edge)
 * 			13 - uint8_t - FPS_frame_per_second)
 * 			14 - uint8_t - MIPI Lane number
 * 			15 - uint8_t - MIPI Video Mode
 * @return int
 */
static int lua_t10_DSI(lua_State *L)
{
	test10.mipi_type = MIPI_DSI;
	test10.timing.ha = lua_tointeger(L, 1);
	test10.timing.hsw = lua_tointeger(L, 2);
	test10.timing.hbp = lua_tointeger(L, 3);
	test10.timing.hfp = lua_tointeger(L, 4);
	test10.timing.va = lua_tointeger(L, 5);
	test10.timing.vsw = lua_tointeger(L, 6);
	test10.timing.vbp = lua_tointeger(L, 7);
	test10.timing.vfp = lua_tointeger(L, 8);
	test10.timing.hsp = lua_tointeger(L, 9);
	test10.timing.vsp = lua_tointeger(L, 10);
	test10.timing.dep = lua_tointeger(L, 11);
	test10.timing.clkEdge = lua_tointeger(L, 12);
	test10.fps = lua_tointeger(L, 13);
	test10.dsi_lane_number = lua_tointeger(L, 14);
	test10.dsi_mode = lua_tointeger(L, 15);

	print_dpi_timing(&test10.timing);
	printf("[LCMTEST] FPS = %d\r\n", test10.fps);

	if (RA8876_check_connection()) {
		printf("ERROR RA8876 not exist\r\n");
		Error_Handler();
	} else {
		printf("[RA8876] Probe Success\r\n");
	}

	uint32_t pclk_Hz = RA8876_initial(&test10.timing, test10.fps);
	pclk_Hz = pclk_Hz;

	uint32_t real_datarate = 0;

	struct ctfb_res_modes mode = {
		.xres = test10.timing.ha,
		.yres = test10.timing.va,
		.refresh = test10.fps,
		.pixclock = 1000000000 / pclk_Hz,
		.pixclock_khz = pclk_Hz / 1000,
		.left_margin = test10.timing.hbp,
		.right_margin = test10.timing.hfp,
		.upper_margin = test10.timing.vbp,
		.lower_margin = test10.timing.vfp,
		.hsync_len = test10.timing.hsw,
		.vsync_len = test10.timing.vsw,
		.sync = 0,
		.vmode = 0,
	};

	uint32_t mipi_dsi_bitrate_per_data_lane_mbps =
		(pclk_Hz * 24 / test10.dsi_lane_number) / 1000000;

	// struct ssd2828_config cfg = {
	test10.ssd2828.gpio_initial = reg_ssd2828_io_initial;
	test10.ssd2828.get_sdo = reg_ssd2828_get_sdo;
	test10.ssd2828.set_csx = reg_ssd2828_set_csx;
	test10.ssd2828.set_sck = reg_ssd2828_set_sck;
	test10.ssd2828.set_reset = reg_ssd2828_set_rst;
	test10.ssd2828.set_sdi = reg_ssd2828_set_sdi;
	test10.ssd2828.ssd2828_tx_clk_khz = SSD2828_OSC;
	test10.ssd2828.ssd2828_color_depth = 24;
	test10.ssd2828.mipi_dsi_number_of_data_lanes = test10.dsi_lane_number;
	test10.ssd2828.mipi_dsi_loosely_packed_pixel_format = 0;
	test10.ssd2828.mipi_dsi_video_mode_operation_type = test10.dsi_mode;
	test10.ssd2828.mipi_dsi_bitrate_per_data_lane_mbps =
		mipi_dsi_bitrate_per_data_lane_mbps;
	test10.ssd2828.mipi_dsi_delay_after_exit_sleep_mode_ms = 100;
	test10.ssd2828.mipi_dsi_delay_after_set_display_on_ms = 100;
	//};

	struct lcd_sync_polarity pol = {
		.hsp = test10.timing.hsp,
		.vsp = test10.timing.vsp,
		.dep = test10.timing.dep,
		.clkEdge = test10.timing.clkEdge,
	};

	// SSD2828_GPIOConfig();

	ssd2828_init(&test10.ssd2828, &mode, &pol);
	ssd2828_LP(&test10.ssd2828);

	lua_pushinteger(L, real_datarate);

	return 0;
}

static int lua_t10_vdd_value(lua_State *L)
{
	// TODO
	return 0;
}

static int lua_t10_vdd_state(lua_State *L)
{
	uint8_t state = lua_tointeger(L, 1);

	if (state == 0) {
		HAL_GPIO_WritePin(CTRL_5V0_GPIO_Port, CTRL_5V0_Pin,
				  GPIO_PIN_RESET);
	} else {
		HAL_GPIO_WritePin(CTRL_5V0_GPIO_Port, CTRL_5V0_Pin,
				  GPIO_PIN_SET);
	}

	return 0;
}

static int lua_t10_vddio_value(lua_State *L)
{
	// TODO
	return 0;
}

static int lua_t10_vddio_state(lua_State *L)
{
	uint8_t state = lua_tointeger(L, 1);

	if (state == 0) {
		HAL_GPIO_WritePin(CTRL_3V3_GPIO_Port, CTRL_3V3_Pin,
				  GPIO_PIN_RESET);
	} else {
		HAL_GPIO_WritePin(CTRL_3V3_GPIO_Port, CTRL_3V3_Pin,
				  GPIO_PIN_SET);
	}

	return 0;
}

static int lua_t10_vdd1v8_state(lua_State *L)
{
	uint8_t state = lua_tointeger(L, 1);

	if (state == 0) {
		HAL_GPIO_WritePin(CTRL_1V8_GPIO_Port, CTRL_1V8_Pin,
				  GPIO_PIN_RESET);
	} else {
		HAL_GPIO_WritePin(CTRL_1V8_GPIO_Port, CTRL_1V8_Pin,
				  GPIO_PIN_SET);
	}

	return 0;
}

static int lua_t10_avdd_value(lua_State *L)
{
	// TODO
	return 1;
}

static int lua_t10_avdd_state(lua_State *L)
{
	// TODO
	return 1;
}

static int lua_t10_vgh_value(lua_State *L)
{
	// TODO
	return 1;
}

static int lua_t10_vgh_state(lua_State *L)
{
	// TODO
	return 1;
}

static int lua_t10_vgl_value(lua_State *L)
{
	// TODO
	return 1;
}

static int lua_t10_vgl_state(lua_State *L)
{
	// TODO
	return 1;
}

static int lua_t10_vcom_value(lua_State *L)
{
	// TODO
	return 1;
}

static int lua_t10_vcom_state(lua_State *L)
{
	// TODO
	return 1;
}

static int lua_t10_getImageFileNames(lua_State *L)
{
	// TODO
	return 1;
}

static int lua_t10_displayImageFile(lua_State *L)
{
	const char *fn = lua_tostring(L, 1);
	drawFile((char *)fn);
	return 0;
}

static int lua_t10_CTP_Initial(lua_State *L)
{
	// TODO
	return 1;
}

static int lua_t10_CTP_Scan(lua_State *L)
{
	// TODO
	return 1;
}

static int lua_t10_CTP_Ckeck(lua_State *L)
{
	// TODO
	return 1;
}

static int lua_t10_RTP_Initial(lua_State *L)
{
	// TODO
	return 1;
}

static int lua_t10_RTP_Scan(lua_State *L)
{
	// TODO
	return 1;
}

static int lua_t10_RTP_Ckeck(lua_State *L)
{
	// TODO
	return 1;
}

static int lua_t10_powerOn(lua_State *L)
{
	HAL_GPIO_WritePin(CTRL_5V0_GPIO_Port, CTRL_5V0_Pin, GPIO_PIN_SET);
	HAL_GPIO_WritePin(CTRL_3V3_GPIO_Port, CTRL_3V3_Pin, GPIO_PIN_SET);
	HAL_GPIO_WritePin(CTRL_1V8_GPIO_Port, CTRL_1V8_Pin, GPIO_PIN_SET);
	return 1;
}

static int lua_t10_powerOff(lua_State *L)
{
	HAL_GPIO_WritePin(CTRL_5V0_GPIO_Port, CTRL_5V0_Pin, GPIO_PIN_RESET);
	HAL_GPIO_WritePin(CTRL_3V3_GPIO_Port, CTRL_3V3_Pin, GPIO_PIN_RESET);
	HAL_GPIO_WritePin(CTRL_1V8_GPIO_Port, CTRL_1V8_Pin, GPIO_PIN_RESET);
	return 1;
}

static int lua_t10_autoPowerControl(lua_State *L)
{
	test10.auto_power_off = lua_tointeger(L, 1);
	return 0;
}

static int lua_fillColor(lua_State *L)
{
	int r = lua_tointeger(L, 1);
	int g = lua_tointeger(L, 2);
	int b = lua_tointeger(L, 3);

	RA8876_GraphicDrawingMode();

	fillColor((r << 16) + (g << 8) + b);
	return 0;
}

static int lua_uart_init(lua_State *L)
{
	return 0;
}

static int lua_uart_write(lua_State *L)
{
	// Check if the first argument is a string
	if (lua_isstring(L, 1)) {
		// Get the string argument from Lua stack
		const char *str = lua_tostring(L, 1);

		// Send the string over UART using HAL_UART_Transmit
		// The length of the string is automatically determined by strlen
		HAL_UART_Transmit(&huart1, (uint8_t *)str, strlen(str),
				  HAL_MAX_DELAY);

		// Return 0 as we don't need to return any value to Lua
		return 0;
	}

	// If the argument is not a string, return an error
	lua_pushstring(L, "Expected a string as the argument");
	lua_error(L); // This will throw an error in Lua
	return 0; // This won't be reached, but added for completeness
}

static int lua_uart_read(lua_State *L)
{
	return 0;
}

static int lua_t10_print(lua_State *L)
{
	int x = lua_tointeger(L, 1);
	int y = lua_tointeger(L, 2);
	int size = lua_tointeger(L, 3);
	int fc = lua_tointeger(L, 4);
	int bc = lua_tointeger(L, 5);
	const char *str = lua_tostring(L, 6);
	// printf(str);

	UNUSED(size);

	RA8876_Select_Font_Height_WxN_HxN_ChromaKey_Alignment(24, 4, 4, 0, 0);
	/*#ifdef MCU_8bit_ColorDepth_8bpp
	RA8876_Print_Internal_Font_String(0,0,1000,1000,0xe0,0x1c, "adfsdfdgfhhgfh");
	#endif
	#ifdef MCU_8bit_ColorDepth_16bpp
	RA8876_Print_Internal_Font_String(0,0,1000,1000,0xf800,0x07e0, "adfsdfdgfhhgfh");
	#endif
	#ifdef MCU_8bit_ColorDepth_24bpp*/
	RA8876_Print_Internal_Font_String(
		x, y, test10.timing.ha, test10.timing.va, fc, bc, (char *)str);
	/*#endif
	#ifdef MCU_16bit_ColorDepth_16bpp
	RA8876_Print_Internal_Font_String(0,0,1000,1000,0xf800,0x07e0, "adfsdfdgfhhgfh");
	#endif
	#ifdef MCU_16bit_ColorDepth_24bpp_Mode_1
	RA8876_Print_Internal_Font_String(0,0,1000,1000,0xff0000,0x00ff00, "adfsdfdgfhhgfh");
	#endif
	#ifdef MCU_16bit_ColorDepth_24bpp_Mode_2
	RA8876_Print_Internal_Font_String(0,0,1000,1000,0xff0000,0x00ff00, "adfsdfdgfhhgfh");
	#endif*/

	return 1;
}

/**
 * @brief
 *
 * @param L
 *
 * @return int
 */
static int lua_t10_print_ex(lua_State *L)
{
	int x = lua_tointeger(L, 1);
	int y = lua_tointeger(L, 2);
	int size = lua_tointeger(L, 3); // base font height 16, 24, 32
	int fc = lua_tointeger(L, 4);
	int bc = lua_tointeger(L, 5);
	const char *str = lua_tostring(L, 6);

	// extend parameters
	int xxn = lua_tointeger(L, 7); // 1~4
	int yxn = lua_tointeger(L, 8); // 1~4
	int chromekey = lua_tointeger(L, 9); // default 0
	int align = lua_tointeger(L, 10); // default 0

	UNUSED(size);

	RA8876_Select_Font_Height_WxN_HxN_ChromaKey_Alignment(size, xxn, yxn,
							      chromekey, align);
	/*#ifdef MCU_8bit_ColorDepth_8bpp
	RA8876_Print_Internal_Font_String(0,0,1000,1000,0xe0,0x1c, "adfsdfdgfhhgfh");
	#endif
	#ifdef MCU_8bit_ColorDepth_16bpp
	RA8876_Print_Internal_Font_String(0,0,1000,1000,0xf800,0x07e0, "adfsdfdgfhhgfh");
	#endif
	#ifdef MCU_8bit_ColorDepth_24bpp*/
	RA8876_Print_Internal_Font_String(
		x, y, test10.timing.ha, test10.timing.va, fc, bc, (char *)str);
	/*#endif
	#ifdef MCU_16bit_ColorDepth_16bpp
	RA8876_Print_Internal_Font_String(0,0,1000,1000,0xf800,0x07e0, "adfsdfdgfhhgfh");
	#endif
	#ifdef MCU_16bit_ColorDepth_24bpp_Mode_1
	RA8876_Print_Internal_Font_String(0,0,1000,1000,0xff0000,0x00ff00, "adfsdfdgfhhgfh");
	#endif
	#ifdef MCU_16bit_ColorDepth_24bpp_Mode_2
	RA8876_Print_Internal_Font_String(0,0,1000,1000,0xff0000,0x00ff00, "adfsdfdgfhhgfh");
	#endif*/
	Graphic_Mode();
	//Goto_Pixel_XY(0, 0);
	Active_Window_XY(0, 0);
	Active_Window_WH(test10.timing.ha, test10.timing.va);
	Memory_XY_Mode();
	Set_Serial_Flash_IF();
	Goto_Pixel_XY(0, 0);
	return 1;
}

/**
 * @brief ms delay
 *
 * @param L
 * 			1 - uint32_t - micro second number count
 * @return int
 */
static int lua_delay_ms(lua_State *L)
{
	int num = lua_tointeger(L, 1);
	HAL_Delay(num);
	return 0;
}

/**
 * @brief ms delay
 *
 * @param L
 * 			1 - uint32_t - micro second number count
 * @return int
 */
static int lua_delay_us(lua_State *L)
{
	int num = lua_tointeger(L, 1);
	DWT_Delay(num);
	return 0;
}
/**
 * @brief functions export to lua
 */

struct luaL_Reg FunctionOfLcmtest10[FunctionOfLcmtest10_Counts] = {
	// version check
	{ "version", lua_check_version },

	// lua stack example
	{ "lua_printString", lua_printString },
	{ "lua_printFloat", lua_printFloat },
	{ "lua_testPushString", lua_testPushString },
	{ "lua_testPushInts", lua_testPushInts },

	// lcd interface define
	{ "t10_DBI_A", lua_t10_DBI_A },
	{ "t10_DBI_B", lua_t10_DBI_B },
	{ "t10_DBI_C", lua_t10_DBI_C },
	{ "t10_DPI", lua_t10_DPI },
	{ "t10_DSI", lua_t10_DSI },

	// test10
	{ "delay_ms", lua_delay_ms },
	{ "delay_us", lua_delay_us },
	{ "led_on", lua_led_on },
	{ "led_off", lua_led_off },
	{ "t10_autoPower", lua_t10_autoPowerControl },
	{ "delay", lua_delay },
	{ "io2", lua_io2 },
	{ "io3", lua_io3 },
	{ "io4", lua_io4 },
	{ "io5", lua_io5 },
	{ "ioInitial", lua_ioInitial },
	{ "ioDeInitial", lua_ioDeInitial },
	{ "ioWrite", lua_ioWrite },
	{ "ioRead", lua_ioRead },
	{ "readKey", lua_readKey },
	{ "drawFile", lua_drawFile },
	{ "set_lvds_color_mode", lua_set_lvds_color_mode },

	{ "uart_init", lua_uart_init },
	{ "uart_write", lua_uart_write },
	{ "uart_read", lua_uart_read },

	// DEBUG
	{ "fillColor", lua_fillColor },
	{ "t10_print", lua_t10_print },
	{ "t10_print_ex", lua_t10_print_ex },

	{ "t10_powerOn", lua_t10_powerOn },
	{ "t10_powerOff", lua_t10_powerOff },
	{ "t10_vdd_value", lua_t10_vdd_value },
	{ "t10_vdd_state", lua_t10_vdd_state },
	{ "t10_vddio_value", lua_t10_vddio_value },
	{ "t10_vddio_state", lua_t10_vddio_state },
	{ "t10_vdd1v8_state", lua_t10_vdd1v8_state },
	{ "t10_avdd_value", lua_t10_avdd_value },
	{ "t10_avdd_state", lua_t10_avdd_state },
	{ "t10_vgh_value", lua_t10_vgh_value },
	{ "t10_vgh_state", lua_t10_vgh_state },
	{ "t10_vgl_value", lua_t10_vgl_value },
	{ "t10_vgl_state", lua_t10_vgl_state },
	{ "t10_vcom_value", lua_t10_vcom_value },
	{ "t10_vcom_state", lua_t10_vcom_state },

	{ "t10_setInterval", lua_t10_setInterval },
	{ "t10_delayMs", lua_t10_delayMs },
	{ "t10_getImageFileNames", lua_t10_getImageFileNames },
	{ "t10_displayImageFile", lua_t10_displayImageFile },

	{ "t10_CTP_Initial", lua_t10_CTP_Initial },
	{ "t10_CTP_Scan", lua_t10_CTP_Scan },
	{ "t10_CTP_Ckeck", lua_t10_CTP_Ckeck },
	{ "t10_RTP_Initial", lua_t10_RTP_Initial },
	{ "t10_RTP_Scan", lua_t10_RTP_Scan },
	{ "t10_RTP_Ckeck", lua_t10_RTP_Ckeck },

	{ NULL, NULL },
};

void runLua(lua_State *L, const char *filename)
{
	FRESULT fr;
	FILINFO fno;
	fr = f_stat(filename, &fno);

	if (fr == FR_OK) {
		printf("[Fatfs] %s Exist, Will be excute\r\n", filename);

		HAL_GPIO_TogglePin(ULED3_GPIO_Port, ULED3_Pin);

		if (luaL_dofile(L, filename)) {
			printf("[lua] luaL_dofile Error: %s\r\n",
			       lua_tostring(L, -1));
		} else {
			printf("[lua] luaL_dofile Success: %s\r\n", filename);
		}
	}
}